/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.supplier.modular.structure.resource.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.listener.CommonDataChangeEventCenter;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.supplier.core.enums.SupplierDataTypeEnum;
import vip.xiaonuo.supplier.modular.structure.relation.entity.SupplierRelation;
import vip.xiaonuo.supplier.modular.structure.relation.enums.SupplierRelationCategoryEnum;
import vip.xiaonuo.supplier.modular.structure.relation.service.SupplierRelationService;
import vip.xiaonuo.supplier.modular.structure.resource.entity.SupplierButton;
import vip.xiaonuo.supplier.modular.structure.resource.entity.SupplierMenu;
import vip.xiaonuo.supplier.modular.structure.resource.enums.SupplierResourceCategoryEnum;
import vip.xiaonuo.supplier.modular.structure.resource.mapper.SupplierButtonMapper;
import vip.xiaonuo.supplier.modular.structure.resource.param.button.SupplierButtonAddParam;
import vip.xiaonuo.supplier.modular.structure.resource.param.button.SupplierButtonEditParam;
import vip.xiaonuo.supplier.modular.structure.resource.param.button.SupplierButtonIdParam;
import vip.xiaonuo.supplier.modular.structure.resource.param.button.SupplierButtonPageParam;
import vip.xiaonuo.supplier.modular.structure.resource.service.SupplierButtonService;
import vip.xiaonuo.supplier.modular.structure.resource.service.SupplierMenuService;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 按钮Service接口实现类
 *
 * @author xuyuxiang
 * @date 2022/6/27 14:25
 **/
@Service
public class SupplierButtonServiceImpl extends ServiceImpl<SupplierButtonMapper, SupplierButton> implements SupplierButtonService {

    @Resource
    private SupplierRelationService supplierRelationService;

    @Resource
    private SupplierMenuService supplierMenuService;

    @Override
    public Page<SupplierButton> page(SupplierButtonPageParam supplierButtonPageParam) {
        QueryWrapper<SupplierButton> queryWrapper = new QueryWrapper<SupplierButton>().checkSqlInjection();
        queryWrapper.lambda().eq(SupplierButton::getCategory, SupplierResourceCategoryEnum.BUTTON.getValue());
        if(ObjectUtil.isNotEmpty(supplierButtonPageParam.getParentId())) {
            queryWrapper.lambda().eq(SupplierButton::getParentId, supplierButtonPageParam.getParentId());
        }
        if(ObjectUtil.isNotEmpty(supplierButtonPageParam.getSearchKey())) {
            queryWrapper.lambda().like(SupplierButton::getTitle, supplierButtonPageParam.getSearchKey());
        }
        if(ObjectUtil.isAllNotEmpty(supplierButtonPageParam.getSortField(), supplierButtonPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(supplierButtonPageParam.getSortOrder());
            queryWrapper.orderBy(true, supplierButtonPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(supplierButtonPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByAsc(SupplierButton::getSortCode);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(SupplierButtonAddParam supplierButtonAddParam) {
        SupplierButton supplierButton = BeanUtil.toBean(supplierButtonAddParam, SupplierButton.class);
        boolean repeatCode = this.count(new LambdaQueryWrapper<SupplierButton>()
                .eq(SupplierButton::getCategory, SupplierResourceCategoryEnum.BUTTON.getValue())
                .eq(SupplierButton::getCode, supplierButton.getCode())) > 0;
        if(repeatCode) {
            throw new CommonException("存在重复的按钮，编码为：{}", supplierButton.getCode());
        }
        supplierButton.setCategory(SupplierResourceCategoryEnum.BUTTON.getValue());
        this.save(supplierButton);

        // 发布增加事件
        CommonDataChangeEventCenter.doAddWithData(SupplierDataTypeEnum.RESOURCE.getValue(), JSONUtil.createArray().put(supplierButton));
    }

    @Override
    public void addForGenButton(String menuId, String className, String functionName,String path) {
        SupplierMenu supplierMenu = supplierMenuService.queryEntity(menuId);
        String classNameFirstLower = StrUtil.lowerFirst(className);//以下修改添加按钮时，同时添加component，并作为后端权限标识  by Mr.wu 2024-03-24
        CollectionUtil.newArrayList(JSONUtil.createObj().set("title", "新增" + functionName).set("code", classNameFirstLower + "Add").set("sortCode", 1).set("component",StrUtil.removePrefix(path, StrUtil.SLASH) + StrUtil.SLASH + "add"),
                JSONUtil.createObj().set("title", "编辑" + functionName).set("code", classNameFirstLower + "Edit").set("sortCode", 2).set("component",StrUtil.removePrefix(path, StrUtil.SLASH) + StrUtil.SLASH + "edit"),
                JSONUtil.createObj().set("title", "删除" + functionName).set("code", classNameFirstLower + "Delete").set("sortCode", 3).set("component",StrUtil.removePrefix(path, StrUtil.SLASH) + StrUtil.SLASH + "delete"),
                JSONUtil.createObj().set("title", "批量删除").set("code", classNameFirstLower + "BatchDelete").set("sortCode", 4).set("component",StrUtil.removePrefix(path, StrUtil.SLASH) + StrUtil.SLASH + "delete")).forEach(jsonObject -> {
            SupplierButtonAddParam supplierButtonAddParam = new SupplierButtonAddParam();
            BeanUtil.copyProperties(jsonObject, supplierButtonAddParam);
            supplierButtonAddParam.setParentId(supplierMenu.getId());
            this.add(supplierButtonAddParam);
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SupplierButtonEditParam supplierButtonEditParam) {
        SupplierButton supplierButton = this.queryEntity(supplierButtonEditParam.getId());
        BeanUtil.copyProperties(supplierButtonEditParam, supplierButton);
        boolean repeatCode = this.count(new LambdaQueryWrapper<SupplierButton>()
                .eq(SupplierButton::getCategory, SupplierResourceCategoryEnum.BUTTON.getValue())
                .eq(SupplierButton::getCode, supplierButton.getCode())
                .ne(SupplierButton::getId, supplierButtonEditParam.getId())) > 0;
        if(repeatCode) {
            throw new CommonException("存在重复的按钮，编码为：{}", supplierButton.getCode());
        }
        this.updateById(supplierButton);

        // 发布更新事件
        CommonDataChangeEventCenter.doUpdateWithData(SupplierDataTypeEnum.RESOURCE.getValue(), JSONUtil.createArray().put(supplierButton));
    }

    @Override
    public void delete(List<SupplierButtonIdParam> supplierButtonIdParamList) {
        List<String> buttonIdList = CollStreamUtil.toList(supplierButtonIdParamList, SupplierButtonIdParam::getId);
        if(ObjectUtil.isNotEmpty(buttonIdList)) {
            // 获取按钮的父菜单id集合
            List<String> parentMenuIdList = supplierMenuService.list(new LambdaQueryWrapper<SupplierMenu>().in(SupplierMenu::getId, buttonIdList)
                    .eq(SupplierMenu::getCategory, SupplierResourceCategoryEnum.BUTTON.getValue())).stream().map(SupplierMenu::getParentId)
                    .collect(Collectors.toList());
            if(ObjectUtil.isNotEmpty(parentMenuIdList)) {
                supplierRelationService.list(new LambdaQueryWrapper<SupplierRelation>().in(SupplierRelation::getTargetId, parentMenuIdList)
                        .eq(SupplierRelation::getCategory, SupplierRelationCategoryEnum.SYS_ROLE_HAS_RESOURCE.getValue())
                        .isNotNull(SupplierRelation::getExtJson)).forEach(supplierRelation -> {
                    JSONObject extJsonObject = JSONUtil.parseObj(supplierRelation.getExtJson());
                    List<String> buttonInfoList = extJsonObject.getBeanList("buttonInfo", String.class);
                    if (ObjectUtil.isNotEmpty(buttonInfoList)) {
                        Set<String> intersectionDistinct = CollectionUtil.intersectionDistinct(buttonIdList, buttonInfoList);
                        if(ObjectUtil.isNotEmpty(intersectionDistinct)) {
                            Collection<String> disjunction = CollectionUtil.disjunction(buttonInfoList, intersectionDistinct);
                            extJsonObject.set("buttonInfo", disjunction);
                        }
                    }
                    // 清除对应的角色与资源信息中的【授权的按钮信息】
                    supplierRelationService.update(new LambdaUpdateWrapper<SupplierRelation>().eq(SupplierRelation::getId, supplierRelation.getId())
                            .set(SupplierRelation::getExtJson, JSONUtil.toJsonStr(extJsonObject)));
                });
                // 执行删除
                this.removeByIds(buttonIdList);

                // 发布删除事件
                CommonDataChangeEventCenter.doDeleteWithDataId(SupplierDataTypeEnum.RESOURCE.getValue(), buttonIdList);
            }
        }
    }

    @Override
    public SupplierButton detail(SupplierButtonIdParam supplierButtonIdParam) {
        return this.queryEntity(supplierButtonIdParam.getId());
    }

    @Override
    public SupplierButton queryEntity(String id) {
        SupplierButton supplierButton = this.getById(id);
        if(ObjectUtil.isEmpty(supplierButton)) {
            throw new CommonException("按钮不存在，id值为：{}", id);
        }
        return supplierButton;
    }
}
